﻿#!/usr/bin/env python
# -*- coding: utf-8 -*-

# widgets.py

# Copyright 2009-2010 Diego Hansen Hahn (aka DiegoHH) <diegohh90 [at] hotmail [dot] com>

# lazynds is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License.

# lazynds is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with lazynds. If not, see <http://www.gnu.org/licenses/>.

import gtk
import gobject
import cairo
import math

import ctypes

LEFT_BUTTON = 1
RIGHT_BUTTON = 3

class Container(gtk.VBox):
    def __init__(self, child,layout, pos, resize = False):
        gtk.VBox.__init__(self)
        x, y = pos

        self.top_border = gtk.DrawingArea()
        self.top_border.add_events(gtk.gdk.BUTTON_PRESS_MASK
                                   |gtk.gdk.BUTTON_RELEASE_MASK
                                   |gtk.gdk.POINTER_MOTION_MASK
                                   |gtk.gdk.BUTTON_MOTION_MASK)

        self.top_border.connect('expose-event', self.do_top_border_expose_event)
        self.top_border.connect('button-press-event', self.do_button_press_event)
        self.top_border.connect('button-release-event', self.do_button_release_event)
        self.top_border.connect('motion-notify-event', self.do_motion_notify_event)
        self.top_border.set_size_request(150,10)

        self.bottom_border = gtk.DrawingArea()
        self.bottom_border.add_events(gtk.gdk.BUTTON_PRESS_MASK
                                   |gtk.gdk.BUTTON_RELEASE_MASK
                                   |gtk.gdk.POINTER_MOTION_MASK
                                   |gtk.gdk.BUTTON_MOTION_MASK)
        self.bottom_border.connect('expose-event', self.do_bottom_border_expose_event)
        if resize:
            self.bottom_border.connect('button-press-event', self.do_bottom_border_button_press_event)
            self.bottom_border.connect('button-release-event', self.do_bottom_border_button_release_event)
            self.bottom_border.connect('motion-notify-event', self.do_bottom_border_motion_notify_event)

        self.bottom_border.set_size_request(150,10)

        self.add_events(gtk.gdk.EXPOSURE_MASK)
        self.pack_start(self.top_border, True, True, 0)

        self.layout = layout
        self.layout.put(self, x,y)
        self.child = child
        self.pack_start(child, True, True, 0)
        self.pack_start(self.bottom_border, True, True, 0)

        self.lock_on_screen = True
        self.position = None

        self.hide = False
        self.bring_to_front = True

    def do_top_border_expose_event(self, widget, event):
        width, height = widget.allocation.width, widget.allocation.height
        cr = event.window.cairo_create()
        cr.rectangle(event.area.x, event.area.y,
                     event.area.width, event.area.height)
        cr.clip()
        cr.set_source_rgb(0.2, 0.3, 0.4)
        radius = height
        cr.arc(radius, radius, radius, math.pi, 1.5*math.pi)
        cr.line_to(width-radius, 0)
        cr.arc(width-radius, radius, radius, 1.5*math.pi, 2*math.pi)
        cr.fill()

    def do_bottom_border_expose_event(self, widget, event):
        width, height = widget.allocation.width, widget.allocation.height
        cr = event.window.cairo_create()
        cr.rectangle(event.area.x, event.area.y,
                     event.area.width, event.area.height)
        cr.clip()
        cr.set_source_rgb(0.2, 0.3, 0.4)
        radius = height
        cr.arc_negative(radius, 0, radius, math.pi, 0.5*math.pi)
        cr.line_to(width-radius, height)
        cr.arc_negative(width-radius, 0, radius, 0.5*math.pi, 0)
        cr.fill()

    def do_bottom_border_button_press_event(self, widget, event):
        if self.bring_to_front:
            for x in self.get_children():
                x.window.raise_()
        self.lock_on_screen = False
        self.position = (int(widget.allocation.width-event.x), int(widget.allocation.height-event.y))
        self.grab_add()

    def do_bottom_border_button_release_event(self, widget, event):
        self.lock_on_screen = True
        self.position = None
        self.grab_remove()

    def do_bottom_border_motion_notify_event(self, widget, event):
        if not self.lock_on_screen and not self.hide:
            x_off, y_off = self.position
            x, y = self.child.translate_coordinates(self, int(event.x), int(event.y))
            x, y = x + x_off , y + y_off
            self.child.set_size_request(x, self.child.get_property('height-request') + y)

    def do_button_press_event(self, widget, event):
        if self.bring_to_front:
            for x in self.get_children():
                x.window.raise_()
        if event.button == LEFT_BUTTON:
            self.lock_on_screen = False
            self.position = (event.x, event.y)
            self.grab_add()
        else:
            if self.hide:
                self.child.show()
                self.hide = False
            else:
                self.child.hide()
                self.hide = True

    def do_button_release_event(self, widget, event):
        if event.button == LEFT_BUTTON:
            self.lock_on_screen = True
            self.position = None
            self.grab_remove()

    def do_motion_notify_event(self, widget, event):
        if not self.lock_on_screen:
            x, y = self.translate_coordinates(self.parent, int(event.x), int(event.y))
            x -= self.position[0]
            y -= self.position[1]
            self.parent.move(self, int(x), int(y))

class BuilderContainer(gtk.Viewport):
    '''
    Construtor para árvore de widgets carregadas pelo GtkBuilder
    '''
    def __init__(self, layout, wtree, x, y):
        gtk.Viewport.__init__(self)
        self.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        self.layout = layout
        self.container = Container(self, self.layout,(x,y))
        wtree.reparent(self)

class ChildContainer(gtk.Viewport):
    '''
    Construtor para árvore de widgets geradas pelo lazy
    '''
    def __init__(self, layout, wtree, x, y, resize = False):
        gtk.Viewport.__init__(self)
        self.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        self.layout = layout
        self.container = Container(self, self.layout,(x,y), resize)
        self.container.bring_to_front = False
        self.add(wtree)

class HexSpinButton(gtk.SpinButton):
    '''
    SpinButton modificado para mostrar números no formato hexadecimal
    '''
    def __init__(self):
        gtk.SpinButton.__init__(self)
        self.connect('input', self.input)
        self.connect('output', self.output)
        self.props.digits = 1

    def input(self, spinbutton, gpointer):
        text = spinbutton.get_text()
        double = ctypes.c_double.from_address(hash(gpointer))
        double.value = int(text, 16)
        return True

    def output(self, spinbutton):
        text = '%08.*X' % (int(spinbutton.props.digits), spinbutton.props.adjustment.value)
        spinbutton.set_text(text)
        return True

class DecoderList(gtk.TreeView):
    ''' Work in Progress '''

    def __init__(self):
        gtk.TreeView.__init__(self)
        self.liststore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
        self.show()

        self.active_list = []

    def append(self, items):
        self.items = items
        for x in self.items.keys():
            self.liststore.append(None, (x, None))

        self.set_model(self.liststore)

    def make(self):
        self.renderer = gtk.CellRendererText()
        self.renderer1 = gtk.CellRendererToggle()
        self.renderer1.set_property('activatable', True)
        self.renderer1.connect( 'toggled', self.col1_toggled_cb, self.liststore )

        self.column0 = gtk.TreeViewColumn(self.col0, self.renderer, text=0)
        self.column1 = gtk.TreeViewColumn(self.col1, self.renderer1)
        self.column1.add_attribute(self.renderer1, 'active', 1)

        self.append_column(self.column1)
        self.append_column(self.column0)

    def set_name(self, col0 = None, col1 = None):
        self.col0 = col0
        self.col1 = col1

    def col1_toggled_cb(self, cell, path, model):
        """
        Sets the toggled state on the toggle button to true or false.
        """
        model[path][1] = not model[path][1]
        #print self.items[model[path][0]]
        if self.items[model[path][0]] not in self.active_list:
            self.active_list.append(self.items[model[path][0]])
        else:
            self.active_list.remove(self.items[model[path][0]])
        return


